/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "输入输出节点.h"

#include "节点/节点树.h"
#include "插座/通用插座.h"
#include "socket_utils.h"



static void f_get子集输出节点(C_节点树* rt, std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : rt->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}

static void f_get子集输入节点(C_节点树* rt, std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : rt->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}



C_输入组节点::C_输入组节点(S_设备环境& ctx, uint32 固定插座数量) : C_节点基类(DEF_输入组节点, E_节点类型::e_节点Type_组输入) {
	m_Name = L"输入组";
	m_Ctx = ctx;

	m_固定插座数量 = 固定插座数量;
}

C_输入组节点::~C_输入组节点() {
}

bool C_输入组节点::f_update() {

	/*C_节点树* rt = f_getThis节点树();
	if (rt && rt->m_程序集) {
		E_JIT_FunParam p;
		p.m_type = m_值.m_Type;
		p.m_data = m_值.m_Value;
		rt->m_节点JIT参数.push_back(p);
		rt->f_getJIT参数ID();
	}*/

	return false;
}

/*std::string C_输入组节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	std::string code;
	return "";

	uint32 num = f_get输出插座Num();
	C_节点树* t = f_getThis节点树();
	//C_节点基类* rn = m_当前节点的子节点树->f_get父节点();

	if (f_NT_是否内联调用(this)) {
		for (uint32 i = 0; i < num; ++i) {
			C_插座基类* inSocket;
			switch (rn->m_Type) {
			case E_节点类型::e_节点Type_循环迭代:
				inSocket = rn->f_get输入插座(i);
				break;
			case E_节点类型::e_节点Type_函数:
				//inSocket = f_get输出插座(i);
				inSocket = rn->f_get输入插座(i);
				break;
			default:
				inSocket = rn->f_get输入插座(i)->f_getLinkOutSocket();
				break;
			}
			//auto outSocket = f_get输出插座(i);
			if (inSocket) {
				f_get输出插座(i)->f_setCode(inSocket->f_getCode());
			}
		}
	}
	else {
		for (uint32 i = 0; i < num; ++i) {
			auto inSocket = rn->f_get输入插座(i);
			//code = f_代码构建_插座变量(*inSocket, t);
			//f_get输出插座(i)->f_setCode(code);
		}
	}
	return "";
}

int16 C_输入组节点::f_可添加删除插座起始位置(E_插座方向 方向) {
	return m_固定插座数量;

	if (方向 == E_插座方向::e_插座Type_输出) {
		
	}
	return C_节点基类::f_可添加删除插座起始位置(方向);
}*/

C_节点基类* f_node_创建输入组节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_输入组节点(ctx);
}

C_节点基类* f_node_加载输入组节点(S_设备环境& ctx, FILE* f) {
	C_输入组节点* node = new C_输入组节点(ctx);
	return node;
}

void f_node_保存输入组节点(C_节点基类* n, FILE* f) {
	C_输入组节点* node = dynamic_cast<C_输入组节点*>(n);
}



C_输出组节点::C_输出组节点(S_设备环境& ctx, uint32 固定插座数量) : C_节点基类(DEF_输出组节点, E_节点类型::e_节点Type_组输出) {
	m_Name = L"输出组";
	m_Ctx = ctx;

	m_固定插座数量 = 固定插座数量;
	m_输入节点 = nullptr;
}

C_输出组节点::~C_输出组节点() {
}

bool C_输出组节点::f_update() {
	
	return false;
}

std::string C_输出组节点::DEF_节点编译函数 {
	m_ReleaseCode = "";
	m_Code = "";

	
	auto* t = f_get所在节点树();
	
	if (t->m_树类型 == E_节点树类型::e_type_函数节点树) {
		uint32 inNum = f_get输入插座Num();

		//std::string m_函数定义;
		for (uint32 i = 1; i < inNum; ++i) {
			auto* socket = f_get输入插座(i);
			//auto* 接入的插座 = socket->f_getLinkOutSocket();
			//if(!接入的插座) continue;
			m_Code += socket->f_构建变量代码(0);

			auto val = socket->f_getCode(0);
			

			if (m_输入节点) {
				uint32 outNum = m_输入节点->f_get输出插座Num();
				bool 是否输出插值引用输入插座 = false;
				for (uint32 i = 0; i < outNum; ++i) {
					auto* socket = m_输入节点->f_get输出插座(i);
			
					if (socket->f_getCode(0) == val) {
						是否输出插值引用输入插座 = true;
						break;
					}
				}
			
				if (是否输出插值引用输入插座) {
					continue;
				}
			}

			auto name = f_代码构建_节点树输出变量名称(this, i);
			if (f_代码构建_数组指针(socket)) {
				m_Code += DEF_S(f_core_array_copy);
				m_Code += "((S_Array*)" + name + ", (S_Array*)" + val + ");\n";
			}
			else {
				m_Code += name + " = " + val + ";\n";
			}
		}

		m_Code += m_ReleaseCode;
	}
	
	return m_Code;
}

C_节点基类* f_node_创建输出组节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_输出组节点(ctx);
}

C_节点基类* f_node_加载输出组节点(S_设备环境& ctx, FILE* f) {
	C_输出组节点* node = new C_输出组节点(ctx);
	return node;
}

void f_node_保存输出组节点(C_节点基类* n, FILE* f) {
	C_输出组节点* node = dynamic_cast<C_输出组节点*>(n);
}





C_插座转接节点::C_插座转接节点(S_设备环境& ctx, uint32 固定插座数量) : C_节点基类(DEF_插座转接节点, E_节点类型::e_节点Type_Reroute) {
	m_Name = L"转接";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建引用插座_I(L"");
	DEF_创建引用插座_O(L"");
	//f_get输出插座(1)->f_set多输入();
}

C_插座转接节点::~C_插座转接节点() {
}

bool C_插座转接节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	if (socket1->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
	}
	socket1 = f_get输入插座(1);
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, socket1->m_Type);

	return false;
}

std::string	C_插座转接节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto* socket1 = f_get输入插座(1);
	if (socket1->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
	}

	
	socket1 = f_get输入插座(1);
	m_Code += socket1->f_构建变量代码(0);
	//socket1->f_getLinkOutSocket();
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, socket1->m_Type);

	f_get输出插座(1)->f_setCode(socket1->f_getCode(0));
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

C_节点基类* f_node_创建插座转接节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_插座转接节点(ctx);
}

C_节点基类* f_node_加载插座转接节点(S_设备环境& ctx, FILE* f) {
	C_插座转接节点* node = new C_插座转接节点(ctx);
	return node;
}

void		f_node_保存插座转接节点(C_节点基类* n, FILE* f) {
	C_插座转接节点* node = dynamic_cast<C_插座转接节点*>(n);
}




C_面板框节点::C_面板框节点(S_设备环境& ctx) : C_节点基类(DEF_面板框节点, E_节点类型::e_节点Type_框) {
	m_Name = L"框";
	m_Ctx = ctx;
}

C_面板框节点::~C_面板框节点() {
	
}

bool C_面板框节点::f_update() {
	return false;
}

void C_面板框节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_面板框节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_创建面板域节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_面板框节点(ctx);
}

C_节点基类* f_node_加载面板域节点(S_设备环境& ctx, FILE* f) {
	C_面板框节点* node = new C_面板框节点(ctx);
	return node;
}

void f_node_保存面板域节点(C_节点基类* n, FILE* f) {
	C_面板框节点* node = dynamic_cast<C_面板框节点*>(n);
}





